home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / winterp-1.13 / src-server / xlisp / xlbfun.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-04  |  19.0 KB  |  859 lines

  1. /* -*-C-*-
  2. ********************************************************************************
  3. *
  4. * File:         xlbfun.c
  5. * RCS:          $Header: xlbfun.c,v 1.4 91/03/24 22:24:21 mayer Exp $
  6. * Description:  xlisp basic built-in functions
  7. * Author:       David Michael Betz
  8. * Created:      
  9. * Modified:     Fri Oct  4 03:37:11 1991 (Niels Mayer) mayer@hplnpm
  10. * Language:     C
  11. * Package:      N/A
  12. * Status:       X11r5 contrib tape release
  13. *
  14. * WINTERP Copyright 1989, 1990, 1991 Hewlett-Packard Company (by Niels Mayer).
  15. * XLISP version 2.1, Copyright (c) 1989, by David Betz.
  16. *
  17. * Permission to use, copy, modify, distribute, and sell this software and its
  18. * documentation for any purpose is hereby granted without fee, provided that
  19. * the above copyright notice appear in all copies and that both that
  20. * copyright notice and this permission notice appear in supporting
  21. * documentation, and that the name of Hewlett-Packard and David Betz not be
  22. * used in advertising or publicity pertaining to distribution of the software
  23. * without specific, written prior permission.  Hewlett-Packard and David Betz
  24. * make no representations about the suitability of this software for any
  25. * purpose. It is provided "as is" without express or implied warranty.
  26. *
  27. * HEWLETT-PACKARD AND DAVID BETZ DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  28. * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
  29. * IN NO EVENT SHALL HEWLETT-PACKARD NOR DAVID BETZ BE LIABLE FOR ANY SPECIAL,
  30. * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  31. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  32. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  33. * PERFORMANCE OF THIS SOFTWARE.
  34. *
  35. * See ./winterp/COPYRIGHT for information on contacting the authors.
  36. * Please send modifications, improvements and bugfixes to mayer@hplabs.hp.com
  37. * Post XLISP-specific questions/information to the newsgroup comp.lang.lisp.x
  38. *
  39. ********************************************************************************
  40. */
  41. static char rcs_identity[] = "@(#)$Header: xlbfun.c,v 1.4 91/03/24 22:24:21 mayer Exp $";
  42.  
  43. #include "xlisp.h"
  44.  
  45. /* external variables */
  46. extern LVAL xlenv,xlfenv,xldenv,true;
  47. extern LVAL s_evalhook,s_applyhook;
  48. /* extern LVAL s_car,s_cdr,s_nth,s_get,s_svalue,s_splist,s_aref; */ /* NPM: commented this out since it is not used in this file */
  49. /* extern LVAL s_lambda,s_macro; */ /* NPM: commented this out since it is not used in this file */
  50. /* extern LVAL s_comma,s_comat; */ /* NPM: commented this out since it is not used in this file */
  51. extern LVAL s_unbound;
  52. extern char gsprefix[];
  53. extern int gsnumber;
  54.  
  55. /* external routines */
  56. extern LVAL xlxeval();
  57.  
  58. /* forward declarations */
  59. /* FORWARD LVAL bquote1(); */    /* NPM: commented this out since it is not used in this file (declared LOCAL in xlcont.c) */
  60. /* FORWARD LVAL defun(); */      /* NPM: commented this out since it is not defined anywhere */
  61. LOCAL FORWARD LVAL makesymbol(); /* NPM: changed this to LOCAL */
  62.  
  63. /* xeval - the built-in function 'eval' */
  64. LVAL xeval()
  65. {
  66.     LVAL expr;
  67.  
  68.     /* get the expression to evaluate */
  69.     expr = xlgetarg();
  70.     xllastarg();
  71.  
  72.     /* evaluate the expression */
  73.     return (xleval(expr));
  74. }
  75.  
  76. /* xapply - the built-in function 'apply' */
  77. LVAL xapply()
  78. {
  79.     LVAL fun,arglist;
  80.  
  81.     /* get the function and argument list */
  82.     fun = xlgetarg();
  83.     arglist = xlgalist();
  84.     xllastarg();
  85.  
  86.     /* apply the function to the arguments */
  87.     return (xlapply(pushargs(fun,arglist)));
  88. }
  89.  
  90. /* xfuncall - the built-in function 'funcall' */
  91. LVAL xfuncall()
  92. {
  93.     LVAL *newfp;
  94.     int argc;
  95.     
  96.     /* build a new argument stack frame */
  97.     newfp = xlsp;
  98.     pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  99.     pusharg(xlgetarg());
  100.     pusharg(NIL); /* will be argc */
  101.  
  102.     /* push each argument */
  103.     for (argc = 0; moreargs(); ++argc)
  104.     pusharg(nextarg());
  105.  
  106.     /* establish the new stack frame */
  107.     newfp[2] = cvfixnum((FIXTYPE)argc);
  108.     xlfp = newfp;
  109.  
  110.     /* apply the function to the arguments */
  111.     return (xlapply(argc));
  112. }
  113.  
  114. /* xmacroexpand - expand a macro call repeatedly */
  115. LVAL xmacroexpand()
  116. {
  117.     LVAL form;
  118.     form = xlgetarg();
  119.     xllastarg();
  120.     return (xlexpandmacros(form));
  121. }
  122.  
  123. /* x1macroexpand - expand a macro call */
  124. LVAL x1macroexpand()
  125. {
  126.     LVAL form,fun,args;
  127.  
  128.     /* protect some pointers */
  129.     xlstkcheck(2);
  130.     xlsave(fun);
  131.     xlsave(args);
  132.  
  133.     /* get the form */
  134.     form = xlgetarg();
  135.     xllastarg();
  136.  
  137.     /* expand until the form isn't a macro call */
  138.     if (consp(form)) {
  139.     fun = car(form);        /* get the macro name */
  140.     args = cdr(form);        /* get the arguments */
  141.     if (symbolp(fun) && fboundp(fun)) {
  142.         fun = xlgetfunction(fun);    /* get the expansion function */
  143.         macroexpand(fun,args,&form);
  144.     }
  145.     }
  146.  
  147.     /* restore the stack and return the expansion */
  148.     xlpopn(2);
  149.     return (form);
  150. }
  151.  
  152. /* xatom - is this an atom? */
  153. LVAL xatom()
  154. {
  155.     LVAL arg;
  156.     arg = xlgetarg();
  157.     xllastarg();
  158.     return (atom(arg) ? true : NIL);
  159. }
  160.  
  161. /* xsymbolp - is this an symbol? */
  162. LVAL xsymbolp()
  163. {
  164.     LVAL arg;
  165.     arg = xlgetarg();
  166.     xllastarg();
  167.     return (arg == NIL || symbolp(arg) ? true : NIL);
  168. }
  169.  
  170. /* xnumberp - is this a number? */
  171. LVAL xnumberp()
  172. {
  173.     LVAL arg;
  174.     arg = xlgetarg();
  175.     xllastarg();
  176.     return (fixp(arg) || floatp(arg) ? true : NIL);
  177. }
  178.  
  179. /* xintegerp - is this an integer? */
  180. LVAL xintegerp()
  181. {
  182.     LVAL arg;
  183.     arg = xlgetarg();
  184.     xllastarg();
  185.     return (fixp(arg) ? true : NIL);
  186. }
  187.  
  188. /* xfloatp - is this a float? */
  189. LVAL xfloatp()
  190. {
  191.     LVAL arg;
  192.     arg = xlgetarg();
  193.     xllastarg();
  194.     return (floatp(arg) ? true : NIL);
  195. }
  196.  
  197. /* xcharp - is this a character? */
  198. LVAL xcharp()
  199. {
  200.     LVAL arg;
  201.     arg = xlgetarg();
  202.     xllastarg();
  203.     return (charp(arg) ? true : NIL);
  204. }
  205.  
  206. /* xstringp - is this a string? */
  207. LVAL xstringp()
  208. {
  209.     LVAL arg;
  210.     arg = xlgetarg();
  211.     xllastarg();
  212.     return (stringp(arg) ? true : NIL);
  213. }
  214.  
  215. /* xarrayp - is this an array? */
  216. LVAL xarrayp()
  217. {
  218.     LVAL arg;
  219.     arg = xlgetarg();
  220.     xllastarg();
  221.     return (vectorp(arg) ? true : NIL);
  222. }
  223.  
  224. /* xstreamp - is this a stream? */
  225. LVAL xstreamp()
  226. {
  227.     LVAL arg;
  228.     arg = xlgetarg();
  229.     xllastarg();
  230.     return (streamp(arg) || ustreamp(arg) ? true : NIL);
  231. }
  232.  
  233. /* xobjectp - is this an object? */
  234. LVAL xobjectp()
  235. {
  236.     LVAL arg;
  237.     arg = xlgetarg();
  238.     xllastarg();
  239.     return (objectp(arg) ? true : NIL);
  240. }
  241.  
  242. /* xboundp - is this a value bound to this symbol? */
  243. LVAL xboundp()
  244. {
  245.     LVAL sym;
  246.     sym = xlgasymbol();
  247.     xllastarg();
  248.     return (boundp(sym) ? true : NIL);
  249. }
  250.  
  251. /* xfboundp - is this a functional value bound to this symbol? */
  252. LVAL xfboundp()
  253. {
  254.     LVAL sym;
  255.     sym = xlgasymbol();
  256.     xllastarg();
  257.     return (fboundp(sym) ? true : NIL);
  258. }
  259.  
  260. /* xnull - is this null? */
  261. LVAL xnull()
  262. {
  263.     LVAL arg;
  264.     arg = xlgetarg();
  265.     xllastarg();
  266.     return (null(arg) ? true : NIL);
  267. }
  268.  
  269. /* xlistp - is this a list? */
  270. LVAL xlistp()
  271. {
  272.     LVAL arg;
  273.     arg = xlgetarg();
  274.     xllastarg();
  275.     return (listp(arg) ? true : NIL);
  276. }
  277.  
  278. /* xendp - is this the end of a list? */
  279. LVAL xendp()
  280. {
  281.     LVAL arg;
  282.     arg = xlgalist();
  283.     xllastarg();
  284.     return (null(arg) ? true : NIL);
  285. }
  286.  
  287. /* xconsp - is this a cons? */
  288. LVAL xconsp()
  289. {
  290.     LVAL arg;
  291.     arg = xlgetarg();
  292.     xllastarg();
  293.     return (consp(arg) ? true : NIL);
  294. }
  295.  
  296. /* xeq - are these equal? */
  297. LVAL xeq()
  298. {
  299.     LVAL arg1,arg2;
  300.  
  301.     /* get the two arguments */
  302.     arg1 = xlgetarg();
  303.     arg2 = xlgetarg();
  304.     xllastarg();
  305.  
  306.     /* compare the arguments */
  307.     return (arg1 == arg2 ? true : NIL);
  308. }
  309.  
  310. /* xeql - are these equal? */
  311. LVAL xeql()
  312. {
  313.     LVAL arg1,arg2;
  314.  
  315.     /* get the two arguments */
  316.     arg1 = xlgetarg();
  317.     arg2 = xlgetarg();
  318.     xllastarg();
  319.  
  320.     /* compare the arguments */
  321.     return (eql(arg1,arg2) ? true : NIL);
  322. }
  323.  
  324. /* xequal - are these equal? (recursive) */
  325. LVAL xequal()
  326. {
  327.     LVAL arg1,arg2;
  328.  
  329.     /* get the two arguments */
  330.     arg1 = xlgetarg();
  331.     arg2 = xlgetarg();
  332.     xllastarg();
  333.  
  334.     /* compare the arguments */
  335.     return (equal(arg1,arg2) ? true : NIL);
  336. }
  337.  
  338. /* xset - built-in function set */
  339. LVAL xset()
  340. {
  341.     LVAL sym,val;
  342.  
  343.     /* get the symbol and new value */
  344.     sym = xlgasymbol();
  345.     val = xlgetarg();
  346.     xllastarg();
  347.  
  348.     /* assign the symbol the value of argument 2 and the return value */
  349.     setvalue(sym,val);
  350.  
  351.     /* return the result value */
  352.     return (val);
  353. }
  354.  
  355. /* xgensym - generate a symbol */
  356. LVAL xgensym()
  357. {
  358.     char sym[STRMAX+11]; /* enough space for prefix and number */
  359.     LVAL x;
  360.  
  361.     /* get the prefix or number */
  362.     if (moreargs()) {
  363.     x = xlgetarg();
  364.     switch (null(x) ? CONS : ntype(x)) {
  365.     case SYMBOL:
  366.         x = getpname(x);
  367.     case STRING:
  368.         strncpy(gsprefix,getstring(x),STRMAX);
  369.         gsprefix[STRMAX] = '\0';
  370.         break;
  371.     case FIXNUM:
  372.         gsnumber = getfixnum(x);
  373.         break;
  374.     default:
  375.         xlerror("bad argument type",x);
  376.     }
  377.     }
  378.     xllastarg();
  379.  
  380.     /* create the pname of the new symbol */
  381.     sprintf(sym,"%s%d",gsprefix,gsnumber++);
  382.  
  383.     /* make a symbol with this print name */
  384.     return (xlmakesym(sym));
  385. }
  386.  
  387. /* xmakesymbol - make a new uninterned symbol */
  388. LVAL xmakesymbol()
  389. {
  390.     return (makesymbol(FALSE));
  391. }
  392.  
  393. /* xintern - make a new interned symbol */
  394. LVAL xintern()
  395. {
  396.     return (makesymbol(TRUE));
  397. }
  398.  
  399. /* makesymbol - make a new symbol */
  400. LOCAL LVAL makesymbol(iflag)
  401.   int iflag;
  402. {
  403.     LVAL pname;
  404.  
  405.     /* get the print name of the symbol to intern */
  406.     pname = xlgastring();
  407.     xllastarg();
  408.  
  409.     /* make the symbol */
  410.     return (iflag ? xlenter(getstring(pname))
  411.               : xlmakesym(getstring(pname)));
  412. }
  413.  
  414. /* xsymname - get the print name of a symbol */
  415. LVAL xsymname()
  416. {
  417.     LVAL sym;
  418.  
  419.     /* get the symbol */
  420.     sym = xlgasymbol();
  421.     xllastarg();
  422.  
  423.     /* return the print name */
  424.     return (getpname(sym));
  425. }
  426.  
  427. /* xsymvalue - get the value of a symbol */
  428. LVAL xsymvalue()
  429. {
  430.     LVAL sym,val;
  431.  
  432.     /* get the symbol */
  433.     sym = xlgasymbol();
  434.     xllastarg();
  435.  
  436.     /* get the global value */
  437.     while ((val = getvalue(sym)) == s_unbound)
  438.     xlunbound(sym);
  439.  
  440.     /* return its value */
  441.     return (val);
  442. }
  443.  
  444. /* xsymfunction - get the functional value of a symbol */
  445. LVAL xsymfunction()
  446. {
  447.     LVAL sym,val;
  448.  
  449.     /* get the symbol */
  450.     sym = xlgasymbol();
  451.     xllastarg();
  452.  
  453.     /* get the global value */
  454.     while ((val = getfunction(sym)) == s_unbound)
  455.     xlfunbound(sym);
  456.  
  457.     /* return its value */
  458.     return (val);
  459. }
  460.  
  461. /* xsymplist - get the property list of a symbol */
  462. LVAL xsymplist()
  463. {
  464.     LVAL sym;
  465.  
  466.     /* get the symbol */
  467.     sym = xlgasymbol();
  468.     xllastarg();
  469.  
  470.     /* return the property list */
  471.     return (getplist(sym));
  472. }
  473.  
  474. /* xget - get the value of a property */
  475. LVAL xget()
  476. {
  477.     LVAL sym,prp;
  478.  
  479.     /* get the symbol and property */
  480.     sym = xlgasymbol();
  481.     prp = xlgasymbol();
  482.     xllastarg();
  483.  
  484.     /* retrieve the property value */
  485.     return (xlgetprop(sym,prp));
  486. }
  487.  
  488. /* xputprop - set the value of a property */
  489. LVAL xputprop()
  490. {
  491.     LVAL sym,val,prp;
  492.  
  493.     /* get the symbol and property */
  494.     sym = xlgasymbol();
  495.     val = xlgetarg();
  496.     prp = xlgasymbol();
  497.     xllastarg();
  498.  
  499.     /* set the property value */
  500.     xlputprop(sym,val,prp);
  501.  
  502.     /* return the value */
  503.     return (val);
  504. }
  505.  
  506. /* xremprop - remove a property value from a property list */
  507. LVAL xremprop()
  508. {
  509.     LVAL sym,prp;
  510.  
  511.     /* get the symbol and property */
  512.     sym = xlgasymbol();
  513.     prp = xlgasymbol();
  514.     xllastarg();
  515.  
  516.     /* remove the property */
  517.     xlremprop(sym,prp);
  518.  
  519.     /* return nil */
  520.     return (NIL);
  521. }
  522.  
  523. /* xhash - compute the hash value of a string or symbol */
  524. LVAL xhash()
  525. {
  526.     unsigned char *str;
  527.     LVAL len,val;
  528.     int n;
  529.  
  530.     /* get the string and the table length */
  531.     val = xlgetarg();
  532.     len = xlgafixnum(); n = (int)getfixnum(len);
  533.     xllastarg();
  534.  
  535.     /* get the string */
  536.     if (symbolp(val))
  537.     str = getstring(getpname(val));
  538.     else if (stringp(val))
  539.     str = getstring(val);
  540.     else
  541.     xlerror("bad argument type",val);
  542.  
  543.     /* return the hash index */
  544.     return (cvfixnum((FIXTYPE)hash(str,n)));
  545. }
  546.  
  547. /* xaref - array reference function */
  548. LVAL xaref()
  549. {
  550.     LVAL array,index;
  551.     int i;
  552.  
  553.     /* get the array and the index */
  554.     array = xlgavector();
  555.     index = xlgafixnum(); i = (int)getfixnum(index);
  556.     xllastarg();
  557.  
  558.     /* range check the index */
  559.     if (i < 0 || i >= getsize(array))
  560.     xlerror("array index out of bounds",index);
  561.  
  562.     /* return the array element */
  563.     return (getelement(array,i));
  564. }
  565.  
  566. /* xmkarray - make a new array */
  567. LVAL xmkarray()
  568. {
  569.     LVAL size;
  570.     int n;
  571.  
  572.     /* get the size of the array */
  573.     size = xlgafixnum() ; n = (int)getfixnum(size);
  574.     xllastarg();
  575.  
  576.     /* create the array */
  577.     return (newvector(n));
  578. }
  579.  
  580. /* xvector - make a vector */
  581. LVAL xvector()
  582. {
  583.     LVAL val;
  584.     int i;
  585.  
  586.     /* make the vector */
  587.     val = newvector(xlargc);
  588.  
  589.     /* store each argument */
  590.     for (i = 0; moreargs(); ++i)
  591.     setelement(val,i,nextarg());
  592.     xllastarg();
  593.  
  594.     /* return the vector */
  595.     return (val);
  596. }
  597.  
  598. /******************************************************************************
  599.  * (copy-array <src> <dest> [<pos>]) --> returns <dest>
  600.  * This function copies from array <src> into the preallocated array <dest>
  601.  * (allocate with 'make-array'). If the optional arg <pos> is given, then
  602.  * elements from <src> will be written into <dest> at index <pos>, otherwise
  603.  * <pos> defaults to 0. 
  604.  *
  605.  * This function was added to xlisp by Niels Mayer.
  606.  ******************************************************************************/
  607. LVAL Prim_COPY_ARRAY()
  608. {
  609.   register int size;
  610.   register LVAL *src, *dest;
  611.   LVAL src_array, dest_array, lval_pos;
  612.  
  613.   src_array = xlgavector();    /* get <src> */
  614.   dest_array = xlgavector();    /* get <dest> */
  615.   if moreargs()
  616.     lval_pos = xlgafixnum();    /* get optional <pos> */
  617.   else
  618.     lval_pos = NIL;
  619.   xllastarg();
  620.  
  621.   src = src_array->n_vdata;
  622.   dest = dest_array->n_vdata;
  623.  
  624.   if (getsize(src_array) < getsize(dest_array))    /* which is shortest? */
  625.     size = getsize(src_array);
  626.   else
  627.     size = getsize(dest_array);
  628.  
  629.   if (lval_pos) {
  630.     int pos = getfixnum(lval_pos);
  631.     int len = getsize(dest_array) - pos;
  632.     if ((len <= 0) || (pos < 0))
  633.       xlerror("Array position out of bounds.", lval_pos);    
  634.     if (len < size)
  635.       size = len;
  636.     dest = dest + pos;
  637.   }
  638.  
  639.   while (size--)
  640.     *dest++ = *src++;
  641.  
  642.   return (dest_array);
  643. }
  644.  
  645. /******************************************************************************
  646.  * (array-insert-pos <array> <pos> <elt>) --> returns the new <array>
  647.  * inserts <elt> at index <pos> in <array>. if <pos> < 0, then <elt> is
  648.  * appended to the end of <array>.
  649.  *
  650.  * This function was added to xlisp by Niels Mayer.
  651.  ******************************************************************************/
  652. LVAL Prim_ARRAY_INSERT_POS()
  653. {
  654.   register int i;
  655.   register LVAL *src, *dest;
  656.   LVAL src_array, dest_array, elt, lval_position;
  657.   int src_size, position;
  658.  
  659.   src_array = xlgavector();    /* get <array> */
  660.   lval_position = xlgafixnum();    /* get <pos>, a fixnum */
  661.   elt = nextarg();        /* get <elt>, which can be any lisp type */
  662.   xllastarg();
  663.  
  664.   src_size = getsize(src_array);
  665.   position = getfixnum(lval_position);
  666.   if (position >= src_size)
  667.     xlerror("Array insertion position out of bounds.", lval_position);
  668.   dest_array = newvector(src_size + 1);
  669.  
  670.   src = src_array->n_vdata;
  671.   dest = dest_array->n_vdata;
  672.  
  673.   if (position < 0) {        /* append <elt> to end of array */
  674.     i = src_size;
  675.     while (i--)
  676.       *dest++ = *src++;
  677.     *dest = elt;
  678.   }
  679.   else {            /* insert <elt> at <position> */
  680.     i = position;
  681.     while (i--)
  682.       *dest++ = *src++;
  683.     *dest++ = elt;
  684.     i = src_size - position;
  685.     while (i--)
  686.       *dest++ = *src++;
  687.   }
  688.   return (dest_array);
  689. }
  690.  
  691. /******************************************************************************
  692.  * (array-delete-pos <array> <pos>) --> returns the new <array>
  693.  * deletes the element at index <pos> in <array>. If <pos>==-1, then it
  694.  * will delete the last element in the array. 
  695.  * Note that this function is destructive. It reuses the old <array>'s
  696.  * elements.
  697.  *
  698.  * This function was added to xlisp by Niels Mayer.
  699.  ******************************************************************************/
  700. LVAL Prim_ARRAY_DELETE_POS()
  701. {
  702.   register int i;
  703.   register LVAL *src, *dest;
  704.   LVAL src_array, dest_array, lval_position;
  705.   int src_size, position;
  706.  
  707.   src_array = xlgavector();    /* get <array> */
  708.   lval_position = xlgafixnum();    /* get <pos>, a fixnum */
  709.   xllastarg();
  710.  
  711.   src_size = getsize(src_array);
  712.   position = getfixnum(lval_position);
  713.   if (position >= src_size)
  714.     xlerror("Array insertion position out of bounds.", lval_position);
  715.   if ((src_size - 1) > 0)
  716.     dest_array = newvector(src_size - 1);
  717.   else
  718.     return (NIL);
  719.  
  720.   src = src_array->n_vdata;
  721.   dest = dest_array->n_vdata;
  722.  
  723.   if (position < 0) {        /* remove last element of array */
  724.     i = src_size - 1;
  725.     while (i--)
  726.       *dest++ = *src++;
  727.   }
  728.   else {            /* remove <elt> at <position> */
  729.     i = position;
  730.     while (i--)
  731.       *dest++ = *src++;
  732.     src++;            /* don't copy the deleted elt */
  733.     i = src_size - (position + 1);
  734.     while (i--)
  735.       *dest++ = *src++;
  736.   }
  737.   return (dest_array);
  738. }
  739.  
  740. /* xerror - special form 'error' */
  741. LVAL xerror()
  742. {
  743.     LVAL emsg,arg;
  744.  
  745.     /* get the error message and the argument */
  746.     emsg = xlgastring();
  747.     arg = (moreargs() ? xlgetarg() : s_unbound);
  748.     xllastarg();
  749.  
  750.     /* signal the error */
  751.     xlerror(getstring(emsg),arg);
  752. }
  753.  
  754. /* xcerror - special form 'cerror' */
  755. LVAL xcerror()
  756. {
  757.     LVAL cmsg,emsg,arg;
  758.  
  759.     /* get the correction message, the error message, and the argument */
  760.     cmsg = xlgastring();
  761.     emsg = xlgastring();
  762.     arg = (moreargs() ? xlgetarg() : s_unbound);
  763.     xllastarg();
  764.  
  765.     /* signal the error */
  766.     xlcerror(getstring(cmsg),getstring(emsg),arg);
  767.  
  768.     /* return nil */
  769.     return (NIL);
  770. }
  771.  
  772. /* xbreak - special form 'break' */
  773. LVAL xbreak()
  774. {
  775.     LVAL emsg,arg;
  776.  
  777.     /* get the error message */
  778.     emsg = (moreargs() ? xlgastring() : NIL);
  779.     arg = (moreargs() ? xlgetarg() : s_unbound);
  780.     xllastarg();
  781.  
  782.     /* enter the break loop */
  783.     xlbreak((emsg ? getstring(emsg) : (unsigned char *)"**BREAK**"),arg);
  784.  
  785.     /* return nil */
  786.     return (NIL);
  787. }
  788.  
  789. /* xcleanup - special form 'clean-up' */
  790. LVAL xcleanup()
  791. {
  792.     xllastarg();
  793.     xlcleanup();
  794. }
  795.  
  796. /* xtoplevel - special form 'top-level' */
  797. LVAL xtoplevel()
  798. {
  799.     xllastarg();
  800.     xltoplevel();
  801. }
  802.  
  803. /* xcontinue - special form 'continue' */
  804. LVAL xcontinue()
  805. {
  806.     xllastarg();
  807.     xlcontinue();
  808. }
  809.  
  810. /* xevalhook - eval hook function */
  811. LVAL xevalhook()
  812. {
  813.     LVAL expr,newehook,newahook,newenv,oldenv,oldfenv,olddenv,val;
  814.  
  815.     /* protect some pointers */
  816.     xlstkcheck(3);
  817.     xlsave(oldenv);
  818.     xlsave(oldfenv);
  819.     xlsave(newenv);
  820.  
  821.     /* get the expression, the new hook functions and the environment */
  822.     expr = xlgetarg();
  823.     newehook = xlgetarg();
  824.     newahook = xlgetarg();
  825.     newenv = (moreargs() ? xlgalist() : NIL);
  826.     xllastarg();
  827.  
  828.     /* bind *evalhook* and *applyhook* to the hook functions */
  829.     olddenv = xldenv;
  830.     xldbind(s_evalhook,newehook);
  831.     xldbind(s_applyhook,newahook);
  832.  
  833.     /* establish the environment for the hook function */
  834.     if (newenv) {
  835.     oldenv = xlenv;
  836.     oldfenv = xlfenv;
  837.     xlenv = car(newenv);
  838.     xlfenv = cdr(newenv);
  839.     }
  840.  
  841.     /* evaluate the expression (bypassing *evalhook*) */
  842.     val = xlxeval(expr);
  843.  
  844.     /* restore the old environment */
  845.     xlunbind(olddenv);
  846.     if (newenv) {
  847.     xlenv = oldenv;
  848.     xlfenv = oldfenv;
  849.     }
  850.  
  851.     /* restore the stack */
  852.     xlpopn(3);
  853.  
  854.     /* return the result */
  855.     return (val);
  856. }
  857.  
  858.